#include "driver_instrumentation.h"
#include "wdm.h"
#include "instrumentation.h"
#include "storm_driver_entries.h"
#include "dispatch_routines.h"


void dispatch(PDEVICE_OBJECT devObj, PIRP Irp) {
  NTSTATUS status;

#if DISPATCH == 1
  #ifdef storm_IRP_MJ_READ
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_READ;
    status = storm_IRP_MJ_READ(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_READ not defined
  #endif

#elif DISPATCH == 2
  #ifdef storm_IRP_MJ_WRITE
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_WRITE;
    status = storm_IRP_MJ_WRITE(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_WRITE not defined
  #endif

#elif DISPATCH == 3
  #ifdef storm_IRP_MJ_DEVICE_CONTROL
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_DEVICE_CONTROL;
    status = storm_IRP_MJ_DEVICE_CONTROL(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_DEVICE_CONTROL not defined
  #endif

#elif DISPATCH == 4
  #ifdef storm_IRP_MJ_INTERNAL_DEVICE_CONTROL
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    status = storm_IRP_MJ_INTERNAL_DEVICE_CONTROL(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_INTERNAL_DEVICE_CONTROL not defined
  #endif
    
#elif DISPATCH == 5
  #ifdef storm_IRP_MJ_POWER
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_POWER;
    status = storm_IRP_MJ_POWER(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_POWER not defined
  #endif

#elif DISPATCH == 6
  #ifdef storm_IRP_MJ_PNP
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_PNP;
    status = storm_IRP_MJ_PNP(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_PNP not defined
  #endif

#elif DISPATCH == 7
  #ifdef storm_IRP_MJ_FLUSH_BUFFERS
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
    status = storm_IRP_MJ_FLUSH_BUFFERS(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_FLUSH_BUFFERS not defined
  #endif

#elif DISPATCH == 8
  #ifdef storm_IRP_MJ_CREATE
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_CREATE;
    status = storm_IRP_MJ_CREATE(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_CREATE not defined
  #endif

#elif DISPATCH == 9
  #ifdef storm_IRP_MJ_CLOSE
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_CLOSE;
    status = storm_IRP_MJ_CLOSE(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_CLOSE not defined
  #endif

#elif DISPATCH == 10
  #ifdef storm_IRP_MJ_CLEANUP
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_CLEANUP;
    status = storm_IRP_MJ_CLEANUP(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_CLEANUP not defined
  #endif

#elif DISPATCH == 11
  #ifdef storm_IRP_MJ_SYSTEM_CONTROL
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SYSTEM_CONTROL;
    status = storm_IRP_MJ_SYSTEM_CONTROL(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SYSTEM_CONTROL not defined
  #endif

#elif DISPATCH == 12
  #ifdef storm_IRP_MJ_QUERY_INFORMATION
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_QUERY_INFORMATION;
    status = storm_IRP_MJ_QUERY_INFORMATION(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_QUERY_INFORMATION not defined
  #endif

#elif DISPATCH == 13
  #ifdef storm_IRP_MJ_SET_INFORMATION
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SET_INFORMATION;
    status = storm_IRP_MJ_SET_INFORMATION(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SET_INFORMATION not defined
  #endif

#elif DISPATCH == 14
  #ifdef storm_IRP_MJ_CREATE_NAMED_PIPE
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
    status = storm_IRP_MJ_CREATE_NAMED_PIPE(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_CREATE_NAMED_PIPE not defined
  #endif

#elif DISPATCH == 15
  #ifdef storm_IRP_MJ_QUERY_EA
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_QUERY_EA;
    status = storm_IRP_MJ_QUERY_EA(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_QUERY_EA not defined
  #endif

#elif DISPATCH == 16
  #ifdef storm_IRP_MJ_SET_EA
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SET_EA;
    status = storm_IRP_MJ_SET_EA(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SET_EA not defined
  #endif

#elif DISPATCH == 17
  #ifdef storm_IRP_MJ_QUERY_VOLUME_INFORMATION
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
    status = storm_IRP_MJ_QUERY_VOLUME_INFORMATION(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_QUERY_VOLUME_INFORMATION not defined
  #endif

#elif DISPATCH == 18
  #ifdef storm_IRP_MJ_SET_VOLUME_INFORMATION
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
    status = storm_IRP_MJ_SET_VOLUME_INFORMATION(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SET_VOLUME_INFORMATION not defined
  #endif

#elif DISPATCH == 19
  #ifdef storm_IRP_MJ_DIRECTORY_CONTROL
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
    status = storm_IRP_MJ_DIRECTORY_CONTROL(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_DIRECTORY_CONTROL not defined
  #endif

#elif DISPATCH == 20
  #ifdef storm_IRP_MJ_FILE_SYSTEM_CONTROL
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
    status = storm_IRP_MJ_FILE_SYSTEM_CONTROL(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_FILE_SYSTEM_CONTROL not defined
  #endif

#elif DISPATCH == 21
  #ifdef storm_IRP_MJ_SHUTDOWN
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SHUTDOWN;
    status = storm_IRP_MJ_SHUTDOWN(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SHUTDOWN not defined
  #endif

#elif DISPATCH == 22
  #ifdef storm_IRP_MJ_LOCK_CONTROL
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_LOCK_CONTROL;
    status = storm_IRP_MJ_LOCK_CONTROL(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_LOCK_CONTROL not defined
  #endif

#elif DISPATCH == 23
  #ifdef storm_IRP_MJ_CREATE_MAILSLOT
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
    status = storm_IRP_MJ_CREATE_MAILSLOT(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_CREATE_MAILSLOT not defined
  #endif

#elif DISPATCH == 24
  #ifdef storm_IRP_MJ_QUERY_SECURITY
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_QUERY_SECURITY;
    status = storm_IRP_MJ_QUERY_SECURITY(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_QUERY_SECURITY not defined
  #endif

#elif DISPATCH == 25
  #ifdef storm_IRP_MJ_SET_SECURITY
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SET_SECURITY;
    status = storm_IRP_MJ_SET_SECURITY(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SET_SECURITY not defined
  #endif

#elif DISPATCH == 26
  #ifdef storm_IRP_MJ_DEVICE_CHANGE
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_DEVICE_CHANGE;
    status = storm_IRP_MJ_DEVICE_CHANGE(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_DEVICE_CHANGE not defined
  #endif

#elif DISPATCH == 27
  #ifdef storm_IRP_MJ_QUERY_QUOTA
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_QUERY_QUOTA;
    status = storm_IRP_MJ_QUERY_QUOTA(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_QUERY_QUOTA not defined
  #endif

#elif DISPATCH == 28
  #ifdef storm_IRP_MJ_SET_QUOTA
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SET_QUOTA;
    status = storm_IRP_MJ_SET_QUOTA(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SET_QUOTA not defined
  #endif

#elif DISPATCH == 29
  #ifdef storm_IRP_MJ_PNP_POWER
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_PNP_POWER;
    status = storm_IRP_MJ_PNP_POWER(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_PNP_POWER not defined
  #endif

#elif DISPATCH == 30
  #ifdef storm_IRP_MJ_SCSI
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_SCSI;
    status = storm_IRP_MJ_SCSI(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_SCSI not defined
  #endif

#elif DISPATCH == 31
  #ifdef storm_IRP_MJ_OTHER
    IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_OTHER;
    status = storm_IRP_MJ_OTHER(devObj, Irp);
  #elif
    #error Function storm_IRP_MJ_OTHER not defined
  #endif

#else
  #error Non existent DISPATCH value
#endif
}

void cancel(PIRP Irp) {
  IoCancelIrp(Irp);
}

void dpc(PDEVICE_OBJECT devObj) {
#ifdef storm_IRP_MJ_DPC_1
  storm_IRP_MJ_DPC_1(NULL, devObj->DeviceExtension, NULL, NULL);
#endif
#ifdef storm_IRP_MJ_DPC_2
  storm_IRP_MJ_DPC_2(NULL, devObj->DeviceExtension, NULL, NULL);
#endif
#ifdef storm_IRP_MJ_DPC_3
  storm_IRP_MJ_DPC_3(NULL, devObj->DeviceExtension, NULL, NULL);
#endif
#ifdef storm_IRP_MJ_DPC_4
  storm_IRP_MJ_DPC_4(NULL, devObj->DeviceExtension, NULL, NULL);
#endif
#ifdef storm_IRP_MJ_DPC_5
  storm_IRP_MJ_DPC_5(NULL, devObj->DeviceExtension, NULL, NULL);
#endif
}


void storm_main ()
{
  NTSTATUS status;
  PDEVICE_OBJECT oldDevObj;
  PDEVICE_OBJECT newDevObj;
  PIRP irp;
  PIO_STACK_LOCATION irpSp;

  // Initialization
  cancelLockStatus = UNLOCKED;

  status = IoCreateDevice(NULL, 1, NULL, 0, 0, 0, &oldDevObj);
  __hv_assume(status == STATUS_SUCCESS);

#ifdef storm_DRIVER_ADD_DEVICE
  status = storm_DRIVER_ADD_DEVICE(NULL, oldDevObj);
  __hv_assume(status == STATUS_SUCCESS);
  newDevObj = oldDevObj->AttachedDevice;
#else
  newDevObj = oldDevObj;
#endif

  irp = IoAllocateIrp(2, FALSE);
  __hv_assume(irp != NULL);
  IoSetNextIrpStackLocation(irp);
  irpSp = IoGetCurrentIrpStackLocation(irp);
  irpSp->DeviceObject = newDevObj;

  myInitDriver(newDevObj, irp);


  // T1: Dispatch
  __async_call dispatch(newDevObj, irp);

  // T2: Cancel routine
  __async_call cancel(irp);

  // T3: Deferred procedure call routine
  __async_call dpc(newDevObj);
}


void __cdecl main() {}

